class Element {
    accept (Visitor) {
        throw new Error("not implement")
    }
}

class ConcreteElementA extends Element {
    accept (visitor) {
        visitor.visitConcreteElement1(this)
    }
    operationA () {
        console.log("ConcreteElement1 operationA")
    }
}

class ConcreteElementB extends Element {
    accept (visitor) {
        visitor.visitConcreteElement2(this)
    }
    operationB () {
        console.log("ConcreteElement2 operationB")
    }
}

class Visitor {
    visitConcreteElement1 (element) {
        console.log("Visitor visitConcreteElement1", element.operationA())
    }
    visitConcreteElement2 (element) {
        console.log("Visitor visitConcreteElement2", element.operationB())
    }
}

const elementA = new ConcreteElementA()
const elementB = new ConcreteElementB()
const visitor = new Visitor()

elementA.accept(visitor)
elementB.accept(visitor)